package net.vinote.smart.platform.service.servlet;

import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.vinote.smart.platform.comm.PlatformConst;
import net.vinote.smart.platform.comm.StringFunction;
import net.vinote.smart.platform.module.database.DBManager;
import net.vinote.smart.platform.module.database.DBManagerFactory;
import net.vinote.smart.platform.module.database.bo.BizObject;
import net.vinote.smart.platform.module.security.Base64;
import net.vinote.smart.platform.service.DWException;
import net.vinote.smart.platform.service.SRE;
import net.vinote.smart.platform.service.bean.CodeLibrary;
import net.vinote.smart.platform.service.bean.DataWindowCatalog;
import net.vinote.smart.platform.service.bean.DataWindowLibrary;
import net.vinote.smart.platform.service.dw.DataWindowClass;
import net.vinote.smart.platform.service.dw.DataWindowClassModify;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;


public class DataWindowExportExcelServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		String doNo = request.getParameter("doNo");
		String whereSql = request.getParameter("whereSql");
		String paramVal = request.getParameter("paramVal");

		DataWindowCatalog dwCatalog = SRE.getDataWindowCatalog(doNo);
		if (dwCatalog == null) {
			throw new DWException("现实模板不存在:doNo=" + doNo);
		}

		Workbook wb = new HSSFWorkbook();
		Sheet sheet = wb.createSheet(dwCatalog.getDoNo());
		sheet.autoSizeColumn(1, true);
		Row headRow = sheet.createRow(0);
		CellStyle style = wb.createCellStyle();
		style.setFillForegroundColor(HSSFColor.GREEN.index);
		style.setFillPattern(CellStyle.SOLID_FOREGROUND);

		List<DataWindowLibrary> libList = SRE.getDataWindowLibrary(doNo);
		List<String> fieldList = new ArrayList<String>(libList.size());
		List<String> virtaulFieldList = new ArrayList<String>();// 存储虚字段
		int index = 0;
		for (DataWindowLibrary lib : libList) {
			String dataObj = StringFunction.nullToBlank(lib.getDataObj())
					.trim();

			// 区分实字段、虚字段以便进行数据查询
			if (dataObj.equals("")) {
				virtaulFieldList.add(lib.getFieldCode());
			} else {
				fieldList.add(dataObj + "." + lib.getColField());
			}

			// 可见字段作为excel Head部分输出
			if (lib.isVisible()) {
				Cell cell = headRow.createCell(index++);
				cell.setCellValue(lib.getFieldName());
				cell.setCellStyle(style);
			}
		}

		String[] fieldArray = new String[fieldList.size()];
		fieldList.toArray(fieldArray);
		String unionTable = dwCatalog.getUnionTable();
		if (unionTable != null && "".equals(unionTable.trim()))
			unionTable = null;
		DBManager bm = DBManagerFactory.getInstance(dwCatalog.getMainTable());
		List<BizObject> dataList = null;
		try {
			dataList = bm.createQuery(fieldArray,
					whereSql != null ? decodeParam(whereSql) : null,
					paramVal != null ? decodeParamVal(paramVal) : null,
					unionTable).getResultList();
		} catch (SQLException e) {
			e.printStackTrace();
		}// 分页查询数据

		if (dataList != null) {
			for (int i = 0; i < dataList.size(); i++) {
				Row row = sheet.createRow(i + 1);
				int j = 0;
				BizObject bo = dataList.get(i);
				for (DataWindowLibrary lib : libList) {
					if (!lib.isVisible()) {
						continue;
					}
					String dataObj = StringFunction.nullToBlank(
							lib.getDataObj()).trim();
					String htmlSrc = lib.getHtmlSource();
					String value = null;
					if ("O".equalsIgnoreCase(dataObj)) {
						value = bo.getAttribute(lib.getColField());
					} else {
						value = bo.getAttribute(dataObj + "."
								+ lib.getColField());
					}
					if ("Code".equals(htmlSrc)) {
						Map<String, CodeLibrary> codeLibMap = SRE
								.getCodeItems(lib.getHtmlVal());
						CodeLibrary codeLib = codeLibMap.get(value);
						if (codeLib != null) {
							row.createCell(j).setCellValue(
									codeLib.getItemName());
						} else {
							row.createCell(j).setCellValue("");
						}

					} else if ("Java".equals(htmlSrc)) {
						row.createCell(j).setCellValue(
								getJavaValue(lib.getHtmlVal(), bo));
					}

					else {
						row.createCell(j).setCellValue(value);
					}
					j++;
				}
			}
		}
		// Write the output to a file
		response.setContentType("application/x-download");
		response.addHeader("Content-Disposition", "attachment;filename="
				+ URLEncoder.encode(dwCatalog.getDoName(), "utf8") + ".xls");
		wb.write(response.getOutputStream());
	}

	public String getJavaValue(String htmlVal, BizObject bo) {
		String val = "";
		try {
			int index = htmlVal.lastIndexOf(".");
			int lparamIndex = htmlVal.indexOf("(");// 左括号
			int rparamIndex = htmlVal.indexOf(")");
			String className = htmlVal.substring(0, index);
			String method = htmlVal.substring(index + 1, lparamIndex);
			String[] param = htmlVal.substring(lparamIndex + 1, rparamIndex)
					.split(",");
			String[] values = new String[param.length];
			Class<?>[] paramClass = new Class[param.length];
			for (int k = 0; k < param.length; k++) {
				paramClass[k] = String.class;
				if (bo != null) {
					values[k] = bo.getAttribute(param[k]);
				} else {
					values[k] = "";
				}
			}
			DataWindowClass dwClass = SRE.getAttribute(
					DataWindowClassModify.class.getName() + "."
							+ PlatformConst.SRE_PREFIX_CLASS_OBJECT + className
							+ "@" + method + "@" + param.length,
					DataWindowClass.class);
			if (dwClass == null) {
				DataWindowClassModify modify = new DataWindowClassModify();
				dwClass = new DataWindowClass();
				Class<?> clazz = Class.forName(className);
				Method m = clazz.getMethod(method, paramClass);
				dwClass.setMethod(m);
				dwClass.setObject(clazz.newInstance());
				modify.put(PlatformConst.SRE_PREFIX_CLASS_OBJECT + className
						+ "@" + method + "@" + param.length, dwClass);
				SRE.addAttribute(modify);
			}
			val = dwClass.getMethod().invoke(dwClass.getObject(), values)
					.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return val;
	}

	/**
	 * 对参数进行解密
	 */
	private String[] decodeParamVal(String str) {
		String[] encryptStr = str.split(PlatformConst.SPLIT_EQ);
		int length = encryptStr.length;
		String[] decodeStr = new String[length];
		for (int i = 0; i < length; i++) {
			decodeStr[i] = decodeParam(encryptStr[i]);
		}
		return decodeStr;
	}

	private String decodeParam(String str) {
		int mod = (4 - str.length() % 4) % 4;
		String temp = "";
		for (int i = 0; i < mod; i++) {
			temp += "=";
		}
		return new String((Base64.decode(str + temp)));
	}
}
